<?php

namespace  Yeevers\Api\Util;


class RSAUtils
{

    /**
     * 公钥加密
     * @param $data
     * @param $publicKey 纯字符串格式
     * @return void
     */
    public static function encript($data,$publicKey){
        if (empty($data)) {
            return 'data参数不能为空';
        }
        if (is_array($data)) {
            return 'data参数不能是数组形式';
        }
        $key = openssl_pkey_get_public(RSAUtils::GetPublicKey($publicKey));
        if (!$key) {
            return('公钥不可用');
        }
        //openssl_public_encrypt 第一个参数只能是string
        //openssl_public_encrypt 第二个参数是处理后的数据
        //openssl_public_encrypt 第三个参数是openssl_pkey_get_public返回的资源类型
        $return_en = openssl_public_encrypt($data, $crypted, $key);
        if (!$return_en) {
            return('加密失败,请检查RSA秘钥');
        }
        return base64_encode($crypted);
    }

    /**
     * 私钥加密
     * @param $data
     * @param $publicKey
     * @return void
     */
    public static function decript($encriptData,$privateKey){
        if (empty($encriptData)) {
            return 'data参数不能为空';
        }
        if (is_array($encriptData)) {
            return 'data参数不能是数组形式';
        }
        $key = openssl_get_privatekey(RSAUtils::GetPrivateKey($privateKey));
        if (!$key) {
            return('私钥不可用');
        }
        //openssl_public_encrypt 第一个参数只能是string
        //openssl_public_encrypt 第二个参数是处理后的数据
        //openssl_public_encrypt 第三个参数是openssl_pkey_get_public返回的资源类型
        $return_de = openssl_private_decrypt(Base64Utils::base64UrlDecode($encriptData), $decrypted, $key);
        if (!$return_de) {
            return('解密失败,请检查RSA秘钥');
        }

        return $decrypted;
    }


    /**

     * 字符串签名

     * @param string $resource 经过urlencode处理过的字符串

     * @return string

     */
    public static function SignStrMessage(string $resource,$privateKey):string {

        $privateKey = openssl_get_privatekey($privateKey);

        $res        = openssl_sign($resource, $signature, $privateKey,OPENSSL_ALGO_SHA256);

        openssl_free_key($privateKey);

        if ($res) {

            return Base64Utils::base64UrlEncode($signature);

        }else {

            throw new \Exception("String Sign Failed",10004);

        }

    }


    /**

     * 字符串签名

     * @param string $resource 经过urlencode处理过的字符串

     * @return string

     */
    public static function Sign(string $resource,string $privateKeyStr):string {

        $privateKey = RSAUtils::GetPrivateKey($privateKeyStr);

        $privateKey = openssl_get_privatekey($privateKey);

        $res        = openssl_sign($resource, $signature, $privateKey,OPENSSL_ALGO_SHA256);

         openssl_free_key($privateKey);

        if ($res) {

            return Base64Utils::base64UrlEncode($signature);

        }else {

            throw new \Exception("String Sign Failed",10004);

        }

    }

    /**
     * 对资源进行签名（版本4）
     *
     * @param string $resource 待签名的资源字符串
     * @param string $privateKeyStr 私钥字符串
     * @return string 签名后的字符串
     * @throws \Exception 当签名失败时抛出异常
     */
    public static function signV4(string $resource, string $privateKeyStr): string
    {
        // 获取私钥
        $privateKey = RSAUtils::GetPrivateKey($privateKeyStr);

        // 将私钥导入openssl资源
        $privateKey = openssl_get_privatekey($privateKey);

        // 使用SHA256算法对资源进行签名
        $res = openssl_sign($resource, $signature, $privateKey, OPENSSL_ALGO_SHA256);

        // 释放私钥资源
        openssl_free_key($privateKey);

        // 如果签名成功，则返回Base64编码的签名字符串
        if ($res) {
            return base64_encode($signature);
        } else {
            // 如果签名失败，则抛出异常
            error_log("String Sign Failed");
            throw new \Exception("String Sign Failed", 10004);
        }
    }


    /**

     * 字符串验签

     * @param string $resource

     * @param string $signature

     * @return bool

     */

    public static function VerifyStrMessage(string $resource,string $signature,string $mch_public_key):bool {

        $signature  = base64_decode($signature);

        $publicKey  = openssl_get_publickey(RSAUtils::GetPublicKey($mch_public_key));

        $res        = openssl_verify($resource, $signature, $publicKey,OPENSSL_ALGO_SHA256);

        openssl_free_key($publicKey);

        return $res===1?true:false;

    }

    /**

     * 获取平台私钥

     * @return string

     */

    public static function GetPrivateKey($privateKey):string {


        $privateKey     = chunk_split($privateKey, 64, "\n");

        $privateKey = "-----BEGIN RSA PRIVATE KEY-----\n$privateKey-----END RSA PRIVATE KEY-----\n";

        return $privateKey;

    }

    /**

     * 获取商户公钥

     * @param string $type

     * @return string

     */

    public static function GetPublicKey($mer_public_key):string{

        $publicKey               = chunk_split($mer_public_key, 64, "\n");

        $publicKey = "-----BEGIN PUBLIC KEY-----\n$publicKey-----END PUBLIC KEY-----\n";

        return $publicKey;

    }

}